from core import LARPEvent, LARPContact
import core
from google.appengine.ext import webapp,db
from google.appengine.ext.webapp import util,template
from google.appengine.api import users
import cgi, os
import logging
import datetime

def Editable(entry):
    # Pass it the owner of an entry; returns TRUE if editable
    # i.e. is None, is Current User, or current user is Admin.
    return entry.owner==None or entry.owner==users.get_current_user() or users.is_current_user_admin()

def Greeting2(origpath='/'):
    # Creates appropriate user greeting and login/out links.
    u=users.get_current_user()
    if u:
        return {"nick":u.nickname(),"url":users.create_logout_url(origpath)}
    else:
        return {"nick":None,"url":users.create_login_url(origpath)}

def CreateTemplate(self,filename,template_values):
	# This is the place to add always-needed template strings.
    path = os.path.join(os.path.dirname(__file__), filename)
    template_values['greeting']=Greeting2()
    template_values['pmsg']=self.request.get('pmsg')
    self.response.out.write(template.render(path, template_values))

def ToDateTime(s):
    # returns the relevant datetime object
    if s=="": return None
    try:
        return datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
    except ValueError:
        return None
    
class WebPage(webapp.RequestHandler):
    def attr(self,attr):
        # returns a clean form request.
        if self.request.get(attr) != None:
            return cgi.escape(self.request.get(attr))
        else:
            return None
            
    def GoHome(self, url='/',pmsg="Done."):
    # Go to a previous (old) page and display a message.
        if '?' in url: # ie, parameter string
            self.redirect("%s&pmsg=%s"%(url,pmsg))
        else:
            self.redirect("%s?pmsg=%s"%(url,pmsg))
    
class ListEntries(WebPage):
    def get(self):
	# Displays all the LARP events
        CreateTemplate(self,
            filename='index.html',
            template_values={'events':db.GqlQuery("SELECT * FROM LARPEvent")})

class DisplayEntry(WebPage):
    # displays a single event
    def get(self, url=None):
        # Get the event details
        if url:
            event=db.GqlQuery("SELECT * FROM LARPEvent WHERE url = :1", url)[0]
        else:
            event=LARPEvent.get(self.attr('key'))
            # Display a prettier url if there is none   
            if event.url:
                self.GoHome("/events/"+event.url,self.attr('pmsg'))
	#Be pretty
        CreateTemplate(self,
            filename='display.html',
            template_values={'event':event, 'editable':Editable(event)})

class EditEntry(WebPage):
    # edits an event. Note: still need to check is unowned or correct user!
    # AddEntry should probably be folded into this; AddEntry is like Edit but blank!
    def get(self):
        event=LARPEvent.get(self.attr('key'))
        # TODO: we should probably grey out Claim Ownership if they are the current owner.
        # Or should we let the owner lose their ownership if they want?
        CreateTemplate(self,
            filename='editevent.html',
            template_values={'event':event,
			     'canedit':Editable(event),
			     'isowner':event.owner==users.get_current_user(),
			     'curent_user':users.get_current_user()})

        #if not Editable(event):
            #self.GoHome(pmsg="You can't edit this record.")

    def post(self):
       event=LARPEvent.get(self.attr('key'))
       if Editable(event):
            #for attr in event.prettyindex:
            #    core.parseattr(attr,self.attr(attr))
            #TODO: turn this into a proper parser that means we don't have to treat 'rand' as a special case
            for attr in ('name','url','tagline','description'):
                setattr(event,attr,self.attr(attr))
            for attr in ('starttime','endtime'):
                setattr(event, attr, ToDateTime(self.attr(attr)))
            event.rand=int(self.attr('rand'))
            if self.attr('own'): event.owner=users.get_current_user()
            event.put()
            self.GoHome()
       else:
            self.GoHome(pmsg="You can't do that!")

class AddEntry(WebPage):
    # handles adding entries to the DB
    def get(self):
        # TODO: need to make URL unique. Tie to key?
        CreateTemplate(self,
            filename='addevent.html',
            template_values={})  

    def post(self):
        # submit data to DB
        # TODO: URL name should be underscored? (the_gathering) - currently fails with spaces.
        # If key_name already exists, overwrites!!!
        # Some things need special handling: i.e. those that need to become integers, are mandatory, etc.
        event = LARPEvent(name=self.attr('name'), rand=int(self.attr('rand')), owner=users.get_current_user())
        for attr in ('tagline','description','url'):
            setattr(event, attr, self.attr(attr)) # equiv: e.url=self.attr('url') etc.
        for attr in ('starttime','endtime'):
            setattr(event, attr, ToDateTime(self.attr(attr)))
        event.put()

        self.GoHome()

class AddContact(WebPage):
    # Creates a new contact.
    # Contacts are people (Head Ref, Treasurer) and places (Vane Tempest, Maelstrom Site)
    def get(self):
        CreateTemplate(self,
            filename='addcontact.html',
            template_values={'eventkey':self.attr('event')})

    def post(self):
        person=LARPContact()
        person.name=self.attr('name')
        person.title=self.attr('title')
        if self.attr('address'):
            person.address=db.PostalAddress(self.attr('address'))
        person.postcode=self.attr('postcode')
        if self.attr('phone'):
            person.phone=db.PhoneNumber(self.attr('phone'))
        if self.attr('email'):
            person.email=db.Email(self.attr('email'))
        if self.attr('lat'):
            person.geopt=db.GeoPt(float(self.attr('lat')),float(self.attr('long')))
            
        person.put()
        if self.attr('event'):
            event=LARPEvent.get(self.attr('event'))
            logging.warn("person.key=%s"%(person.key()))
            event.contacts.append(str(person.key()))
            event.put()
        self.GoHome('bindcontact?event=%s'%(str(event.key())))

class BindContact(WebPage):
    # Links contacts to an event or redirects to create a new one.
    # clist is needed to allow a nice way of getting information about the
    # contacts relevant to a single event without requesting ALL the contacts
    # in the DB which is wasteful.
    def get(self):
        assert self.attr('event')
        event=LARPEvent.get(self.attr('event'))
        clist=[]
        for contact in event.contacts:
            logging.warn("*%s*"%contact)
            try:
                clist.append(LARPContact.get(contact))
            except:
                logging.error('Failed to append to clist')
                raise
        CreateTemplate(self,
            filename='bindcontact.html',
            template_values={'editable':Editable(event),
                             'event':event,
                             'eventcontacts':clist,
                             'globalcontacts':db.GqlQuery("SELECT * FROM LARPContact"),
			})  
		# note: passing globalcontacts is wasteful if they don't have
		# edit permissions! It might be worth having a separate page for this
		# or having a failfilter to start with.
                    
    def post(self):
        event=LARPEvent.get(self.attr('event'))
        bindto=self.request.get_all('bindto')
	logging.warn("bindto:%s"%(bindto))
        assert Editable(event)
        for i in bindto:
            event.contacts.append(i)
        event.put()
        if bindto==[]:
            self.GoHome('bindcontact?event=%s'%(str(event.key())),'Nothing to do!')
        else:
            self.GoHome('bindcontact?event=%s'%(str(event.key())))
         
         # cgi.escape(self.request.get(attr))
        
class ViewContact(WebPage):
    # displays a single event
    def get(self, url=None):
        # Get the event details
        if url:
            contact=db.GqlQuery("SELECT * FROM LARPContact WHERE url = :1", url)[0]
        else:
            contact=LARPContact.get(self.attr('key'))
            # Display a prettier url if there is none   
            if contact.url:
                self.GoHome("/contact/"+contact.url,self.attr('pmsg'))
	#Be pretty
        CreateTemplate(self,
            filename='viewcontact.html',
            template_values={'contact':contact, 'editable':Editable(contact)})

            
def main(): # orig
    application = webapp.WSGIApplication([('/', ListEntries),
                                          ('/add', AddEntry),
                                          ('/list', ListEntries),
                                          ('/show', DisplayEntry),
                                          ('/edit', EditEntry),
                                          ('/events/(.*)', DisplayEntry),
                                          ('/addcontact', AddContact),
                                          ('/bindcontact', BindContact),
                                          ('/viewcontact', ViewContact),
                                          #('/removecontact', RemoveContact),
                                          ],
                                         debug=True)

    util.run_wsgi_app(application)


if __name__ == '__main__': #orig
    main()
